<template>
  <div class="demo-container">
    <h2>Vue 3 与 Web Components 集成</h2>
    <p class="description">
      探索 Vue 3 如何与原生 Web Components 无缝集成，包括使用自定义元素、插槽和事件通信。
    </p>

    <!-- 特性简介 -->
    <div class="feature-intro">
      <div class="feature-card">
        <h3>📦 自定义元素使用</h3>
        <p>Vue 3 可以直接使用和操作原生 Web Components</p>
      </div>
      <div class="feature-card">
        <h3>🔌 组件封装</h3>
        <p>将 Vue 组件包装为标准 Web Components 以在任何框架中使用</p>
      </div>
      <div class="feature-card">
        <h3>🔄 双向通信</h3>
        <p>实现 Vue 组件与 Web Components 之间的事件和属性通信</p>
      </div>
    </div>

    <!-- 示例部分 -->
    <section class="example-section">
      <h3>1. 使用原生自定义元素</h3>
      
      <!-- 注册自定义元素 -->
      <button @click="registerCustomElement" class="demo-button">
        注册自定义元素
      </button>
      
      <!-- 使用自定义元素 -->
      <div class="demo-box" v-if="customElementRegistered">
        <my-custom-element 
          ref="customElementRef"
          :message="customElementMessage"
          @custom-event="handleCustomEvent"
        ></my-custom-element>
        
        <div class="controls">
          <input 
            v-model="customElementMessage" 
            placeholder="修改消息内容"
            class="input-field"
          />
          <button @click="updateCustomElement" class="demo-button">
            更新元素
          </button>
        </div>
        
        <div v-if="customEventData" class="event-data">
          <p><strong>接收到的自定义事件数据：</strong>{{ customEventData }}</p>
        </div>
      </div>

      <CodeBlock :code="customElementExampleCode"
      </CodeBlock>
    </section>

    <section class="example-section">
      <h3>2. 将 Vue 组件导出为 Web Component</h3>
      
      <div class="demo-box">
        <p>以下是如何将 Vue 组件封装为 Web Component 的示例：</p>
        <button @click="showWebComponentCode" class="demo-button">
          查看实现代码
        </button>
        
        <div v-if="showWebComponentImplementation" class="code-display">
          <CodeBlock :code="vueToWebComponentExampleCode"
          </CodeBlock>
        </div>
      </div>
    </section>

    <section class="example-section">
      <h3>3. 使用 Vue 3 的 Web Components 插件</h3>
      
      <div class="demo-box">
        <p>Vue 3 提供了插件方式配置 Web Components 集成：</p>
        
        <CodeBlock :code="webComponentsPluginExampleCode"
        </CodeBlock>
      </div>
    </section>

    <section class="example-section">
      <h3>4. 实际应用示例：产品卡片组件</h3>
      
      <div class="demo-box">
        <button @click="registerProductCardElement" class="demo-button">
          注册产品卡片自定义元素
        </button>
        
        <div class="products-container" v-if="productCardRegistered">
          <product-card 
            v-for="product in products" 
            :key="product.id"
            :name="product.name"
            :price="product.price"
            :description="product.description"
            @add-to-cart="addToCart($event, product)"
          ></product-card>
        </div>
        
        <div v-if="cart.length > 0" class="cart-section">
          <h4>购物车 ({{ cart.length }})</h4>
          <ul class="cart-items">
            <li v-for="item in cart" :key="item.id">
              {{ item.name }} - ${{ item.price }}
            </li>
          </ul>
        </div>
      </div>
    </section>

    <!-- 最佳实践部分 -->
    <section class="best-practices">
      <h3>最佳实践</h3>
      
      <div class="practice-item">
        <h4>✅ 使用 Vue 3 的 defineCustomElement</h4>
        <p>利用 Vue 3 内置的 defineCustomElement API 来创建标准的 Web Components</p>
      </div>
      
      <div class="practice-item">
        <h4>✅ 配置 isCustomElement</h4>
        <p>在 Vue 应用配置中正确识别自定义元素，避免 Vue 尝试解析它们</p>
      </div>
      
      <div class="practice-item">
        <h4>✅ 注意事件冒泡</h4>
        <p>在 Web Components 中使用 composed: true 允许事件冒泡穿过 Shadow DOM 边界</p>
      </div>
      
      <div class="practice-item">
        <h4>✅ 处理样式隔离</h4>
        <p>利用 Shadow DOM 的样式隔离特性，同时注意全局样式可能需要通过 CSS Custom Properties 穿透</p>
      </div>
    </section>
  </div>
</template>

<script>
// CodeBlock 组件用于显示代码示例
import CodeBlock from '@components/CodeBlock.vue'

// 代码示例常量定义
const customElementExampleCode = `// 注册自定义元素示例
class MyCustomElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
  }

  connectedCallback() {
    this.render();
    // 发送自定义事件
    setTimeout(() => {
      this.dispatchEvent(new CustomEvent('custom-event', {
        detail: '来自Web Component的问候！',
        bubbles: true,
        composed: true
      }));
    }, 1000);
  }

  static get observedAttributes() {
    return ['message'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'message') {
      this.render();
    }
  }

  render() {
    const message = this.getAttribute('message') || '默认消息';
    this.shadowRoot.innerHTML = \`
      <style>
        :host {
          display: block;
          padding: 16px;
          background-color: #f0f0f0;
          border-radius: 8px;
          border: 2px solid #42b883;
        }
        .message {
          font-size: 18px;
          color: #333;
        }
      </style>
      <div class="message">\${message}</div>
    \`;
  }
}`;

const vueToWebComponentExampleCode = `// 1. 创建 Vue 组件
const MyVueComponent = {
  template: \`
    <div class="vue-web-component">
      <h3>{{ title }}</h3>
      <p>{{ description }}</p>
      <button @click="handleClick">点击我</button>
    </div>
  \`,
  props: {
    title: String,
    description: String
  },
  methods: {
    handleClick() {
      this.$emit('vue-component-click', {
        timestamp: new Date().toISOString()
      });
    }
  }
};

// 2. 注册为 Web Component
import { defineCustomElement } from 'vue';

// 将 Vue 组件转换为自定义元素构造函数
const MyVueWebComponent = defineCustomElement({
  // 使用 Vue 组件选项
  ...MyVueComponent,
  // 自定义元素的额外选项
  styles: [
    \`
      .vue-web-component {
        padding: 20px;
        background-color: #e6f7ff;
        border-radius: 8px;
        border: 1px solid #91d5ff;
      }
      button {
        margin-top: 10px;
        padding: 8px 16px;
        background-color: #1890ff;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
    \`
  ]
});

// 注册自定义元素
customElements.define('my-vue-web-component', MyVueWebComponent);`;

const webComponentsPluginExampleCode = `import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

// 配置 Vue 应用与 Web Components 的交互
app.config.compilerOptions.isCustomElement = (tag) => {
  // 识别自定义元素
  return tag.startsWith('my-') || tag.includes('-')
}

// 注册为全局属性以便在组件中使用
app.config.globalProperties.$customElements = {
  register: (name, component) => {
    // 注册自定义元素的辅助方法
  }
}

app.mount('#app')`;

export default {
  name: 'WebComponentsIntegrationDemo',
  components: {
    CodeBlock
  },
  data() {
    return {
      customElementRegistered: false,
      customElementMessage: 'Hello from Vue to Web Component!',
      customElementRef: null,
      customEventData: null,
      showWebComponentImplementation: false,
      productCardRegistered: false,
      products: [
        {
          id: 1,
          name: 'Vue 3 进阶指南',
          price: 29.99,
          description: '掌握 Vue 3 高级特性和最佳实践'
        },
        {
          id: 2,
          name: 'Web Components 实战',
          price: 39.99,
          description: '深入学习 Web Components 标准和应用'
        },
        {
          id: 3,
          name: '前端架构设计',
          price: 49.99,
          description: '构建可扩展的前端应用架构'
        }
      ],
      cart: []
    }
  },
  methods: {
    // 注册自定义元素
    registerCustomElement() {
      // 检查是否已经注册
      if (customElements.get('my-custom-element')) {
        this.customElementRegistered = true;
        return;
      }

      // 定义自定义元素类
      class MyCustomElement extends HTMLElement {
        constructor() {
          super();
          this.attachShadow({ mode: 'open' });
        }

        connectedCallback() {
          this.render();
          // 发送自定义事件
          setTimeout(() => {
            this.dispatchEvent(new CustomEvent('custom-event', {
              detail: '来自Web Component的问候！',
              bubbles: true,
              composed: true
            }));
          }, 1000);
        }

        static get observedAttributes() {
          return ['message'];
        }

        attributeChangedCallback(name, oldValue, newValue) {
          if (name === 'message' && oldValue !== newValue) {
            this.render();
          }
        }

        render() {
          const message = this.getAttribute('message') || '默认消息';
          this.shadowRoot.innerHTML = `
            <style>
              :host {
                display: block;
                padding: 16px;
                background-color: #f0f0f0;
                border-radius: 8px;
                border: 2px solid #42b883;
              }
              .message {
                font-size: 18px;
                color: #333;
              }
            </style>
            <div class="message">${message}</div>
          `;
        }
      }

      // 注册自定义元素
      customElements.define('my-custom-element', MyCustomElement);
      this.customElementRegistered = true;
    },

    // 更新自定义元素
    updateCustomElement() {
      if (this.customElementRef) {
        this.customElementRef.setAttribute('message', this.customElementMessage);
      }
    },

    // 处理自定义事件
    handleCustomEvent(event) {
      this.customEventData = event.detail;
    },

    // 显示Web Component实现代码
    showWebComponentCode() {
      this.showWebComponentImplementation = !this.showWebComponentImplementation;
    },

    // 注册产品卡片自定义元素
    registerProductCardElement() {
      // 检查是否已经注册
      if (customElements.get('product-card')) {
        this.productCardRegistered = true;
        return;
      }

      // 定义产品卡片自定义元素
      class ProductCard extends HTMLElement {
        constructor() {
          super();
          this.attachShadow({ mode: 'open' });
        }

        connectedCallback() {
          this.render();
          // 添加按钮点击事件
          const button = this.shadowRoot.querySelector('button');
          button.addEventListener('click', () => {
            this.dispatchEvent(new CustomEvent('add-to-cart', {
              bubbles: true,
              composed: true
            }));
          });
        }

        static get observedAttributes() {
          return ['name', 'price', 'description'];
        }

        attributeChangedCallback(name) {
          if (['name', 'price', 'description'].includes(name)) {
            this.render();
          }
        }

        render() {
          const name = this.getAttribute('name') || '产品名称';
          const price = this.getAttribute('price') || '0';
          const description = this.getAttribute('description') || '产品描述';
          
          this.shadowRoot.innerHTML = `
            <style>
              :host {
                display: inline-block;
                width: 280px;
                margin: 10px;
                padding: 16px;
                background-color: white;
                border-radius: 8px;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
              }
              h4 {
                margin-top: 0;
                color: #333;
              }
              .price {
                font-size: 18px;
                font-weight: bold;
                color: #ff4d4f;
              }
              p {
                color: #666;
                font-size: 14px;
              }
              button {
                width: 100%;
                padding: 8px;
                background-color: #1890ff;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                margin-top: 10px;
              }
              button:hover {
                background-color: #40a9ff;
              }
            </style>
            <div class="product-card">
              <h4>${name}</h4>
              <div class="price">$${price}</div>
              <p>${description}</p>
              <button>加入购物车</button>
            </div>
          `;
        }
      }

      // 注册自定义元素
      customElements.define('product-card', ProductCard);
      this.productCardRegistered = true;
    },

    // 添加到购物车
    addToCart(event, product) {
      this.cart.push({ ...product });
    }
  }
}
</script>

<style scoped>
:root {
  --apple-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.demo-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

h2 {
  color: #333;
  text-align: center;
  margin-bottom: 20px;
}

h3 {
  color: #42b883;
  margin-top: 30px;
  margin-bottom: 20px;
  border-bottom: 1px solid #eaeaea;
  padding-bottom: 10px;
}

h4 {
  color: #333;
  margin-bottom: 10px;
}

.description {
  text-align: center;
  color: #666;
  margin-bottom: 30px;
  font-size: 16px;
}

.feature-intro {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 40px;
}

.feature-card {
  flex: 1;
  background: #f8f9fa;
  border-radius: 8px;
  padding: 20px;
  text-align: center;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.feature-card h3 {
  border-bottom: none;
  margin-top: 0;
  color: #42b883;
}

.example-section {
  background: white;
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 30px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  transition: all 0.2s ease;
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* 深色模式下的液态玻璃效果 */
@media (prefers-color-scheme: dark) {
  .example-section {
    background: rgba(28, 28, 30, 0.8);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  }
}

.demo-box {
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  padding: 20px;
  margin: 15px 0;
  transition: var(--apple-transition);
}

/* 深色模式下的液态玻璃效果 */
@media (prefers-color-scheme: dark) {
  .demo-box {
    background: rgba(28, 28, 30, 0.8);
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
}

.demo-button {
  background-color: #42b883;
  color: white;
  border: none;
  border-radius: 4px;
  padding: 8px 16px;
  cursor: pointer;
  font-size: 14px;
  margin: 10px 5px 10px 0;
  transition: background-color 0.3s;
}

.demo-button:hover {
  background-color: #3aa876;
}

.input-field {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  margin-right: 10px;
  width: 300px;
}

.controls {
  margin-top: 15px;
  display: flex;
  align-items: center;
}

.event-data {
  margin-top: 15px;
  padding: 10px;
  background-color: #e6f7ff;
  border-left: 4px solid #1890ff;
  border-radius: 4px;
}

.code-display {
  margin-top: 20px;
}

.products-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  margin-top: 20px;
}

.cart-section {
  margin-top: 20px;
  padding: 15px;
  background-color: #fff7e6;
  border-radius: 8px;
}

.cart-items {
  list-style: none;
  padding: 0;
  margin: 10px 0 0 0;
}

.cart-items li {
  padding: 8px 0;
  border-bottom: 1px solid #ffd591;
}

.best-practices {
  background: rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  padding: 20px;
  margin-top: 40px;
  transition: all 0.2s ease;
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* 深色模式下的液态玻璃效果 */
@media (prefers-color-scheme: dark) {
  .best-practices {
    background: rgba(35, 35, 37, 0.8);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.1);
  }
}

.practice-item {
  margin-bottom: 15px;
  padding: 10px;
  background: white;
  border-radius: 6px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

.practice-item h4 {
  margin-top: 0;
  color: #1890ff;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .feature-intro {
    flex-direction: column;
  }
  
  .controls {
    flex-direction: column;
    align-items: stretch;
  }
  
  .input-field {
    width: 100%;
    margin-right: 0;
    margin-bottom: 10px;
  }
  
  .products-container {
    justify-content: center;
  }
}
</style>